package cc.jinglupeng.wechat.api;

import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;

import org.apache.log4j.Logger;

import cc.jinglupeng.wechat.bean.oauth.OAuthAccessToken;
import cc.jinglupeng.wechat.bean.oauth.OAuthUser;
import cc.jinglupeng.wechat.util.WxHttpUtils;

/**
 * OAuth授权API
 * 
 * @author jinglupeng.cc
 */
public class OAuth2API {

	private static Logger logger = Logger.getLogger(OAuth2API.class);

	private static final String OAUTH2URL = "https://open.weixin.qq.com/connect/oauth2/authorize";
	private static final String OAUTH2_GET_ACCESSTOKEN = "https://api.weixin.qq.com/sns/oauth2/access_token?appid=APPID&secret=APPSECRET&code=CODE&grant_type=authorization_code";
	private static final String OAUTH2_REFRESH_TOKEN = "https://api.weixin.qq.com/sns/oauth2/refresh_token?appid=APPID&grant_type=refresh_token&refresh_token=REFRESH_TOKEN";
	private static final String OAUTH2_GET_USERINFO = "https://api.weixin.qq.com/sns/userinfo?access_token=ACCESS_TOKEN&openid=OPENID&lang=zh_CN";

	/**
	 * 获取OAuth2授权API，不弹出授权页面，直接跳转，只能获取用户openid
	 * 
	 * @param appId
	 *            -第三方用户唯一凭证
	 * @param uri
	 *            -授权后重定向的回调链接地址
	 * @return
	 */
	public static String generateOAuth2BaseUrl(String appId, String uri) {
		try {
			uri = URLEncoder.encode(uri, "UTF-8");
		} catch (UnsupportedEncodingException e) {
			logger.error(e.getMessage());
			return null;
		}
		StringBuilder sb = new StringBuilder(OAUTH2URL);
		sb.append("?appid=" + appId);
		sb.append("&redirect_uri=" + uri);
		sb.append("&response_type=code");
		sb.append("&scope=snsapi_base");
		sb.append("&state=0");
		sb.append("#wechat_redirect");
		return sb.toString();
	}

	/**
	 * 获取OAuth2授权API，弹出授权页面，可通过openid拿到昵称、性别、所在地。并且，即使在未关注的情况下，只要用户授权，也能获取其信息
	 * 
	 * @param appId
	 *            -第三方用户唯一凭证
	 * @param uri
	 *            -授权后重定向的回调链接地址
	 * @return
	 */
	public static String generateOAuth2UserInfoUrl(String appId, String uri) {
		try {
			uri = URLEncoder.encode(uri, "UTF-8");
		} catch (UnsupportedEncodingException e) {
			logger.error(e.getMessage());
			return null;
		}
		StringBuilder sb = new StringBuilder(OAUTH2URL);
		sb.append("?appid=" + appId);
		sb.append("&redirect_uri=" + uri);
		sb.append("&response_type=code");
		sb.append("&scope=snsapi_userinfo");
		sb.append("&state=0");
		sb.append("#wechat_redirect");
		return sb.toString();
	}

	/**
	 * 通过code换取网页授权access_token
	 * 
	 * @param appId
	 *            -第三方用户唯一凭证
	 * @param code
	 *            -code
	 * @return
	 */
	public static OAuthAccessToken getAccessToken(String appId, String code) {
		String appSecret = BaseAPI.getAppSecret(appId);
		if (appSecret == null) {
			logger.error("通过code换取网页授权access_token失败,获取Appsecret失败，AppId:"
					+ appId);
			return new OAuthAccessToken(-6, "获取Appsecret失败！");
		}
		String url = OAUTH2_GET_ACCESSTOKEN.replaceAll("APPID", appId)
				.replaceAll("APPSECRET", appSecret).replaceAll("CODE", code);
		try {
			return WxHttpUtils.get(url, OAuthAccessToken.class);
		} catch (Exception e) {
			logger.error("获取网页授权access_token失败，错误信息:" + e.getMessage());
			return new OAuthAccessToken(-5, "未知错误！");
		}
	}

	/**
	 * 刷新网页授权access_token
	 * 
	 * @param appId
	 *            -第三方用户唯一凭证
	 * @param refreshToken
	 *            -refreshToken
	 * @return
	 */
	public static OAuthAccessToken refreshAccessToken(String appId,
			String refreshToken) {
		String appSecret = BaseAPI.getAppSecret(appId);
		if (appSecret == null) {
			logger.error("刷新网页授权access_token,获取Appsecret失败，AppId:" + appId);
			return new OAuthAccessToken(-6, "获取Appsecret失败！");
		}
		String url = OAUTH2_REFRESH_TOKEN.replaceAll("APPID", appId)
				.replaceAll("REFRESH_TOKEN", refreshToken);
		try {
			return WxHttpUtils.get(url, OAuthAccessToken.class);
		} catch (Exception e) {
			logger.error("刷新网页授权access_token失败，错误信息:" + e.getMessage());
			return new OAuthAccessToken(-5, "未知错误！");
		}
	}

	/**
	 * 通过网页授权AccessToken拉取用户信息
	 * 
	 * @param accessToken
	 *            -网页授权AccessToken
	 */
	public static OAuthUser getUserInfo(String accessToken, String openId) {
		String url = OAUTH2_GET_USERINFO
				.replaceAll("ACCESS_TOKEN", accessToken).replaceAll("OPENID",
						openId);
		try {
			return WxHttpUtils.get(url, OAuthUser.class);
		} catch (Exception e) {
			logger.error("通过网页授权AccessToken拉取用户信息失败，错误信息:" + e.getMessage());
			return new OAuthUser(-5, "未知错误！");
		}
	}

}
